package com.aplink.generic.widgets;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import android.content.pm.PackageManager.NameNotFoundException;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

import com.aplink.generic.GenericFragment;
import com.aplink.generic.adapter.ConfigAdapter;
import com.aplink.generic.adapter.SelectionAdapter;
import com.aplink.generic.constant.type.ListViewSelection;
import com.aplink.generic.database.SqlMethods;
import com.aplink.generic.dictionary.GenericDictionary;
import com.aplink.generic.interfaces.OnGetObjProInfo;
import com.aplink.generic.interfaces.OnSearchListener;
import com.aplink.generic.pojo.ColumnSetting;
import com.aplink.generic.pojo.ContentData;
import com.aplink.generic.pojo.GenericAttribute;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.controlspec.ControlSpec;
import com.aplink.generic.pojo.controlspec.ListviewSpec;
import com.aplink.generic.util.LogUtil;
import com.aplink.generic.util.ResourcesHelper;
import com.aplink.generic.util.objectrule.Target;
import com.aplink.generic.util.objectrule.TargetCollection;
import com.aplink.generic.xmlparser.ColumnSettingParser;
import com.aplink.generic.xmlparser.ContentDataParser;

public class ApLinkListView extends ApLinkBaseView implements OnSearchListener {

    /**
     * 
     */
    private static final long serialVersionUID = -3260220465175116431L;
    private ArrayList<ColumnSetting> columnSettings;
    private int headerIndex = 0;
    private ArrayList<GenericObject> mArrDeletes;
    private ArrayList<GenericObject> mArrInserts;
    private final ContentData mContentData;
    private final SparseArray<GenericObject> mDeleteObjects;
    private ConfigAdapter mGenericConfigAdapter;
    private ArrayList<GenericObject> mGenericObjects;
    private final SparseArray<GenericObject> mInsertObjects;
    private ArrayList<GenericObject> mListMainObjects;
    private final ListView mListView;
    private final ListViewSelection mListViewSelection;
    private final ListviewSpec mListviewSpecFormat;
    private String mMappingName;
    private final OnItemClickListener mOnRowClickListener = new OnItemClickListener() {

        @Override
        public void onItemClick(final AdapterView<?> arg0, final View arg1,
                final int index, final long arg3) {
            if (ApLinkListView.this.mListviewSpecFormat.getTargetCollection() != null) {
                final String fullClassName = null;
                try {
                    final GenericObject genericObject = ApLinkListView.this.mGenericConfigAdapter
                            .getDisplayObjects().get(
                                    index - ApLinkListView.this.headerIndex);
                    final Target targetActivity = ApLinkListView.this.targetCollection
                            .getTargetClass(genericObject);
                    ApLinkListView.this.getGenericFragment().startActivity(
                            targetActivity.getTargetClass(),
                            targetActivity.getPassingValue(), genericObject);
                } catch (final ClassNotFoundException e) {
                    LogUtil.error(fullClassName + " is not found",
                            "List view item click", getClass());
                } catch (final NameNotFoundException e) {
                    e.printStackTrace();
                }
            } else {
                if (ApLinkListView.this.mListViewSelection != null) {
                    final SparseBooleanArray sparseBooleanArray = ApLinkListView.this.mListView
                            .getCheckedItemPositions();
                    if (ApLinkListView.this.mListViewSelection
                            .equals(ListViewSelection.MULTIPLE_SELECTION)) {
                        final GenericObject genericObject = ApLinkListView.this.mSelectionAdapter
                                .getObject(index);
                        if (sparseBooleanArray.get(index)) {
                            ApLinkListView.this.mInsertObjects.put(index,
                                    genericObject);
                            if (ApLinkListView.this.mDeleteObjects.get(index) != null) {
                                ApLinkListView.this.mDeleteObjects
                                        .remove(index);
                            }
                        } else {
                            ApLinkListView.this.mDeleteObjects.put(index,
                                    genericObject);
                            if (ApLinkListView.this.mInsertObjects.get(index) != null) {
                                ApLinkListView.this.mInsertObjects
                                        .remove(index);
                            }
                        }
                    } else if (ApLinkListView.this.mListViewSelection
                            .equals(ListViewSelection.SINGLE_SELECTION)) {
                        final GenericObject genericObject = ApLinkListView.this.mSelectionAdapter
                                .getObject(index);
                        ApLinkListView.this.mInsertObjects.clear();
                        ApLinkListView.this.mDeleteObjects.clear();
                        ApLinkListView.this.mInsertObjects.put(index,
                                genericObject);
                    }
                }
            }
        }
    };

    private final ArrayList<Integer> mSelectedPositions;

    private SelectionAdapter mSelectionAdapter;

    private TargetCollection targetCollection;

    public ApLinkListView(final GenericFragment dataEntryActivity,
            final ControlSpec controlSpec, final View view) {
        super(dataEntryActivity, controlSpec, view);
        this.mListView = (ListView) view;
        this.mListviewSpecFormat = (ListviewSpec) controlSpec;
        this.targetCollection = this.mListviewSpecFormat.getTargetCollection();
        this.mContentData = ContentDataParser.getInstance().parseIntoObjProp(
                this.mListviewSpecFormat.getContentDataID());
        this.targetCollection = this.mListviewSpecFormat.getTargetCollection();
        this.mInsertObjects = new SparseArray<GenericObject>();
        this.mDeleteObjects = new SparseArray<GenericObject>();
        this.mListViewSelection = this.mListviewSpecFormat
                .getListViewSelection();
        if (this.mListViewSelection != null) {
            if (!this.mListviewSpecFormat.getListViewSelection().equals(
                    ListViewSelection.NONE)) {
                final SqlMethods sqlMethods = getGenericFragment()
                        .getSqlMethods();
                final ContentData contentData = getGenericFragment()
                        .getContentData();
                this.mListMainObjects = getGenericFragment().getDatabaseGet()
                        .getList(contentData, sqlMethods.toString());
                this.mMappingName = this.mListviewSpecFormat.getDataObject()
                        + "." + this.mListviewSpecFormat.getMappingName();
            }
        }
        this.mArrDeletes = new ArrayList<GenericObject>();
        this.mArrInserts = new ArrayList<GenericObject>();
        this.mSelectedPositions = new ArrayList<Integer>();
    }

    @Override
    public void clear() {
        // TODO Auto-generated method stub

    }

    private ConfigAdapter generateConfigAdapter() {
        this.columnSettings = ColumnSettingParser.parse(getGenericFragment(),
                this.mListviewSpecFormat.getRptrdesignID());
        return new ConfigAdapter(getGenericFragment(), this.mGenericObjects,
                this.columnSettings, this.mListviewSpecFormat.getRowItem());
    }

    public ArrayList<GenericObject> getArrDeletes() {
        return this.mArrDeletes;
    }

    public ArrayList<GenericObject> getArrInserts() {
        return this.mArrInserts;
    }

    @Override
    public GenericAttribute getAttribute() {
        return null;
    }

    public ContentData getContentData() {
        return this.mContentData;
    }

    public ArrayList<GenericObject> getDeleteList() {
        final ArrayList<GenericObject> arrayList = new ArrayList<GenericObject>();
        for (int i = 0; i < this.mDeleteObjects.size(); i++) {
            final int mainIndex = this.mDeleteObjects.keyAt(i);
            arrayList.add(this.mListMainObjects.get(mainIndex));
            this.mArrDeletes.add(this.mListMainObjects.get(mainIndex));
        }
        return arrayList;
    }

    public ConfigAdapter getGenericConfigAdapter() {
        return this.mGenericConfigAdapter;
    }

    public ArrayList<GenericObject> getInsertList() {
        final ArrayList<GenericObject> arrayList = new ArrayList<GenericObject>();
        for (int i = 0; i < this.mInsertObjects.size(); i++) {
            final int mainIndex = this.mInsertObjects.keyAt(i);
            final GenericAttribute genericAttribute = GenericAttribute.obtain(
                    this.mSelectionAdapter.getValue(mainIndex),
                    this.mListviewSpecFormat.getMappingName());
            final boolean isForceRenew = this.mListViewSelection
                    .equals(ListViewSelection.MULTIPLE_SELECTION);
            final GenericObject genericObject = getGenericFragment()
                    .getBindingObject(isForceRenew);
            genericObject.put(this.mListviewSpecFormat.getDataObject() + "."
                    + this.mListviewSpecFormat.getMappingName(),
                    genericAttribute);
            arrayList.add(genericObject);
            this.mArrInserts.add(genericObject);
            try {
                Thread.sleep(2000);
            } catch (final InterruptedException e) {
                e.printStackTrace();
            }
        }
        return arrayList;
    }

    @Override
    public GenericDictionary<String, GenericAttribute> getListAttributes() {
        final GenericDictionary<String, GenericAttribute> hashMap = new GenericDictionary<String, GenericAttribute>();
        if (!this.mListviewSpecFormat.getListViewSelection().equals(
                ListViewSelection.NONE)) {
            final SparseBooleanArray sparseBooleanArray = this.mListView
                    .getCheckedItemPositions();
            for (int i = 0; i < this.mSelectionAdapter.getCount(); i++) {
                if (sparseBooleanArray.get(i)) {
                    final GenericAttribute genericAttribute = GenericAttribute
                            .obtain(this.mSelectionAdapter.getValue(i),
                                    this.mListviewSpecFormat.getMappingName());
                    hashMap.put(this.mListviewSpecFormat.getDataObject() + "."
                            + this.mListviewSpecFormat.getMappingName(),
                            genericAttribute);
                }
            }
        }
        return hashMap;
    }

    public ListViewSelection getListViewSelection() {
        return this.mListViewSelection;
    }

    public OnSearchListener getOnSearchListener() {
        return this;
    }

    @Override
    public ListView getView() {
        return this.mListView;
    }

    private void handleSelection(final SelectionAdapter selectionAdapter) {
        if (this.mListMainObjects != null) {
            for (final GenericObject genericObject : this.mListMainObjects) {
                final String value = genericObject.getValue(this.mMappingName);
                final int index = selectionAdapter.getPosition(value);
                if (index != -1) {
                    this.mListView.setItemChecked(index, true);
                    this.mSelectedPositions.add(index);
                }
            }
        }
    }

    @Override
    protected void initViewProperties() {
        final LayoutInflater inflater = getActivity().getLayoutInflater();
        final String headerView = this.mListviewSpecFormat.getHeader();
        final String footerView = this.mListviewSpecFormat.getFooter();
        if (headerView != null) {
            final int headerViewId = ResourcesHelper
                    .getLayoutIdByName(headerView);
            final ViewGroup header = (ViewGroup) inflater.inflate(headerViewId,
                    this.mListView, false);
            this.mListView.addHeaderView(header, null, false);
            this.headerIndex = 1;
        }
        if (footerView != null) {
            final int footerViewId = ResourcesHelper
                    .getLayoutIdByName(footerView);
            final ViewGroup footer = (ViewGroup) inflater.inflate(footerViewId,
                    this.mListView, false);
            this.mListView.addFooterView(footer);
        }

        if ((this.mListviewSpecFormat.getListViewSelection() != null)
                && !this.mListviewSpecFormat.getListViewSelection().equals(
                        ListViewSelection.NONE)) {
            this.mListView.setChoiceMode(this.mListviewSpecFormat
                    .getListViewSelection().getValue());
        }
    }

    @Override
    protected void loadBindingObject() {
        SqlMethods whereClause = SqlMethods.getInstance();
        if (!this.mListviewSpecFormat.isLoadAll()) {
            whereClause = getGenericFragment().getSqlMethods();
        }
        this.mGenericObjects = getDatabaseGet().getList(this.mContentData,
                whereClause == null ? null : whereClause.toString());
        if (this.mGenericObjects != null) {
            if (this.mListviewSpecFormat.getListViewSelection().equals(
                    ListViewSelection.NONE)) {
                this.mGenericConfigAdapter = generateConfigAdapter();
                this.mListView.setAdapter(this.mGenericConfigAdapter);
            } else if (this.mListviewSpecFormat.getListViewSelection().equals(
                    ListViewSelection.SINGLE_SELECTION)) {
                this.mSelectionAdapter = new SelectionAdapter(
                        getApplicationContext(),
                        android.R.layout.simple_list_item_single_choice,
                        this.mGenericObjects, this.mListviewSpecFormat);
                this.mListView.setAdapter(this.mSelectionAdapter);
                handleSelection(this.mSelectionAdapter);
            } else if (this.mListviewSpecFormat.getListViewSelection().equals(
                    ListViewSelection.MULTIPLE_SELECTION)) {
                this.mSelectionAdapter = new SelectionAdapter(
                        getApplicationContext(),
                        android.R.layout.simple_list_item_multiple_choice,
                        this.mGenericObjects, this.mListviewSpecFormat);
                this.mListView.setAdapter(this.mSelectionAdapter);
                handleSelection(this.mSelectionAdapter);
            }
        }
    }

    @Override
    protected void loadDefaultObject() {
        this.mGenericObjects = getDatabaseGet()
                .getList(this.mContentData, null);
        if (this.mGenericObjects != null) {
            if (this.mListviewSpecFormat.getListViewSelection().equals(
                    ListViewSelection.NONE)) {
                this.mGenericConfigAdapter = generateConfigAdapter();
                this.mListView.setAdapter(this.mGenericConfigAdapter);
            } else if (this.mListviewSpecFormat.getListViewSelection().equals(
                    ListViewSelection.SINGLE_SELECTION)) {
                this.mSelectionAdapter = new SelectionAdapter(
                        getApplicationContext(),
                        android.R.layout.simple_list_item_single_choice,
                        this.mGenericObjects, this.mListviewSpecFormat);
                this.mListView.setAdapter(this.mSelectionAdapter);
            } else if (this.mListviewSpecFormat.getListViewSelection().equals(
                    ListViewSelection.MULTIPLE_SELECTION)) {
                this.mSelectionAdapter = new SelectionAdapter(
                        getApplicationContext(),
                        android.R.layout.simple_list_item_multiple_choice,
                        this.mGenericObjects, this.mListviewSpecFormat);
                this.mListView.setAdapter(this.mSelectionAdapter);
            }
        }
    }

    @Override
    public void onSearch(final ArrayList<String> searchFields,
            final String queryString) {
        this.mGenericConfigAdapter.getFilter(searchFields).filter(queryString);
    }

    @Override
    public void onSearchClose() {
        this.mGenericConfigAdapter.getFilter(null).filter(null);
    }

    private void setAdapter(final ArrayList<GenericObject> genericObjects) {
        this.mGenericConfigAdapter.setDisplayResult(genericObjects);
        this.mGenericConfigAdapter.notifyDataSetChanged();
    }

    public void setArrDeletes(final ArrayList<GenericObject> arrDeletes) {
        this.mArrDeletes = arrDeletes;
    }

    public void setArrInserts(final ArrayList<GenericObject> arrInserts) {
        this.mArrInserts = arrInserts;
    }

    @Override
    protected void setEventListener() {
        this.mListView.setOnItemClickListener(this.mOnRowClickListener);
    }

    public void setGenericConfigAdapter(final ConfigAdapter genericConfigAdapter) {
        this.mGenericConfigAdapter = genericConfigAdapter;
    }

    @Override
    public void setObjPropInfoTemp(final OnGetObjProInfo getObjProInfo) {
        throw new UnsupportedOperationException(this.getClass().getSimpleName()
                + " is not support this method");
    }

    @Override
    public void setOnClickListener(final OnClickListener onClickListener) {
        throw new UnsupportedOperationException(this.getClass().getSimpleName()
                + " is not support this method");
    }

    public void sort(final Comparator<GenericObject> comparator) {
        if (this.mGenericObjects != null) {
            final ArrayList<GenericObject> resultGenericObjects = this.mGenericObjects;
            Collections.sort(resultGenericObjects, comparator);
            setAdapter(resultGenericObjects);
        }
    }

}
